package com.alibaba.citrus.ots.forecast.repository.impl;

import com.alibaba.citrus.ots.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.ots.common.exception.FunctionException;
import com.alibaba.citrus.ots.forecast.common.DateUtils;
import com.alibaba.citrus.ots.forecast.common.MoneyUtil;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.constants.ForecastConstants;
import com.alibaba.citrus.ots.forecast.repository.ForecastOrderLineQueryRepository;
import com.alibaba.citrus.ots.forecast.repository.ForecastOrderQueryRepository;
import com.alibaba.citrus.ots.forecast.repository.impl.converter.ForecastOrderRepositoryConverter;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.SalesPlanQueryService;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.PageQuerySalePlanRequest;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.model.dto.PageQuerySalesPlanLineList2Request;
import com.epoch.app.bcots.model.dto.PageQuerySalesPlanLineList2Response;
import com.epoch.app.bcots.model.dto.SalesPlanLineSDO2;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.bcots.service.SalesPlanService;
import com.epoch.app.otsb2btradecenter.model.dto.CountSaleOrderForReportRequest;
import com.epoch.app.otsb2btradecenter.model.dto.CountSaleOrderForReportResponse;
import com.epoch.app.otsb2btradecenter.service.OtsB2bTradeCenterService;
import com.epoch.app.otsforecastsales.domian.forecastorderline.dto.BatchLoadListRequest;
import com.epoch.app.otsforecastsales.domian.forecastorderline.dto.BatchLoadListResponse;
import com.epoch.app.otsforecastsales.domian.forecastorderline.dto.LoadForecastOrderLineRequest;
import com.epoch.app.otsforecastsales.domian.forecastorderline.dto.LoadListByDealStatusRequest;
import com.epoch.app.otsforecastsales.domian.forecastorderline.dto.LoadListByDealStatusResponse;
import com.epoch.app.otsforecastsales.domian.forecastorderline.model.ForecastOrderLine;
import com.epoch.app.otsforecastsales.domian.forecastorderline.service.ForecastOrderLineService;
import com.epoch.app.otsforecastsales.dto.request.DealForecastListRequest;
import com.epoch.app.otsforecastsales.dto.response.DealForecastOrderResponse;
import com.epoch.app.otsforecastsales.dto.response.QueryForecastLineResponse;
import com.epoch.app.otsforecastsales.forecastorderlineindex.model.ForecastOrderLineIndex;
import com.epoch.app.otsforecastsales.forecastorderlineindex.service.ForecastOrderLineIndexService;
import com.epoch.app.otsforecastsales.model.dto.ActivitySDO;
import com.epoch.app.otsforecastsales.model.dto.SearchForecastOrderRequest;
import com.epoch.app.otsforecastsales.model.dto.SelectCombox;
import com.epoch.app.otsforecastsales.sdo.ForecastOrderLineSDO;
import com.epoch.app.otsforecastsales.sdo.ForecastOrderSDO;
import com.epoch.app.otsplatformenhance.inventoryallotquery.service.InventoryAllotQueryService;
import com.epoch.app.otsplatformenhance.model.dto.BatchQueryAllotRequest;
import com.epoch.app.otsplatformenhance.model.dto.DailyInventoryLine;
import com.epoch.app.otsplatformenhance.model.dto.PageQueryAddressListRequest;
import com.epoch.app.otsplatformenhance.model.dto.PageQueryAddressListResponse;
import com.epoch.app.otsplatformenhance.model.dto.QueryDailyAllotOrderLine;
import com.epoch.app.otsplatformenhance.model.dto.QueryResolveInventoryResponse;
import com.epoch.app.otsplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.otsplatformenhance.service.OtsPlatformEnhanceService;
import com.epoch.app.otspricecenter.api.creditquery.service.CreditQueryService;
import com.epoch.app.otspricecenter.api.pricequery.service.PriceQueryService;
import com.epoch.app.otspricecenter.dto.request.DimensionPropertyInfoRequest;
import com.epoch.app.otspricecenter.dto.request.HumanInfoRequest;
import com.epoch.app.otspricecenter.dto.request.MaterialInfoRequest;
import com.epoch.app.otspricecenter.dto.request.PlaceInfoRequest;
import com.epoch.app.otspricecenter.dto.request.PriceQueryRequest;
import com.epoch.app.otspricecenter.dto.response.ItemPriceResponse;
import com.epoch.app.otspricecenter.dto.response.PriceQueryResponse;
import com.epoch.app.otspricecenter.model.dto.CreditReponse;
import com.epoch.app.otspricecenter.model.dto.QueryCreditRequest;
import com.epoch.app.otsunifiedinventory.model.dto.GetListWarehouseStockRequest;
import com.epoch.app.otsunifiedinventory.model.dto.WarehouseInventory;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.math3.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: qiaojiange
 * @create: 2021/09/15
 * @Description 预报单子单查询
 */
@Service
public class ForecastOrderLineQueryRepositoryImpl implements ForecastOrderLineQueryRepository {
    @Autowired
    private InventoryAllotQueryService inventoryAllotQueryService;
    @Resource
    ForecastOrderLineService forecastOrderLineService;
    @Resource
    ForecastOrderQueryRepository forecastOrderQueryRepository;
    @Resource
    PriceQueryService priceQueryService;
    @Resource
    ForecastOrderLineIndexService forecastOrderLineIndexService;
    @Autowired
    BaseDataService baseDataService;
    @Autowired
    CreditQueryService creditQueryService;
    @Autowired
    private SalesPlanService salesPlanService;
    @Autowired
    private OtsB2bTradeCenterService otsB2bTradeCenterService;
    @Autowired
    private SalesPlanQueryService salesPlanQueryService;
    @Autowired
    OtsPlatformEnhanceService otsPlatformEnhanceService;

    Log log = Log.getLogger(ForecastOrderLineQueryRepositoryImpl.class);
    @Resource(name = "scItemsQueryTaskExecutor")
    private ThreadPoolTaskExecutor scItemsQueryTaskExecutor;

    @Resource(name="forecastSaleTaskExecutor")
    ThreadPoolTaskExecutor forecastSaleTaskExecutor;

    @Resource
    private ApplicationContext applicationContext;

    private static final String REPORTED_QUANTITY = "reported";
    private static final String REMAIN_QUANTITY = "remain";

    // 每日库存查询循环查询较多， 参数重复度高， 增加30秒的缓存
    Cache<String, QueryResolveInventoryResponse> inventoryCache = CacheBuilder.newBuilder()
            .maximumSize(3000) // 设置缓存的最大容量
            .expireAfterWrite(60, TimeUnit.SECONDS) // 设置缓存在写入一分钟后失效
            .concurrencyLevel(10) // 设置并发级别为10
            .recordStats() // 开启缓存统计
            .build();

    // 每日库存查询循环查询较多， 参数重复度高， 增加30秒的缓存
    Cache<String, DailyInventoryLine> dailyInventoryCache = CacheBuilder.newBuilder()
            .maximumSize(3000) // 设置缓存的最大容量
            .expireAfterWrite(60, TimeUnit.SECONDS) // 设置缓存在写入一分钟后失效
            .concurrencyLevel(10) // 设置并发级别为10
            .recordStats() // 开启缓存统计
            .build();

    @Override
    @RepositoryInvoker(printLog = true)
    public List<ForecastOrderLineSDO> queyrLineDetailList(ForecastOrderLineSDO sdo) {
        //根据主订单查询子单集合
        ForecastOrderLine forecastOrderLineLoadListRequest = new ForecastOrderLine();
        forecastOrderLineLoadListRequest.setMainOrderId(sdo.getMainOrderId());
        forecastOrderLineLoadListRequest.setScItemId(sdo.getScItemId());
        Result<List<ForecastOrderLine>> listResult = forecastOrderLineService.loadForecastOrderLineList(forecastOrderLineLoadListRequest);
        List<ForecastOrderLine> result = listResult.getResult();
        //结果封装转换
        List<ForecastOrderLineSDO> forecastOrderLineSDOArrayList = null;
        if (CollectionUtils.isNotEmpty(result)) {
            forecastOrderLineSDOArrayList = result.stream().map(forecastOrderLine -> {
                ForecastOrderLineSDO forecastOrderLineSDO = new ForecastOrderLineSDO();
//            BeanUtils.copyProperties(forecastOrderLine,forecastOrderLineSDO);
                forecastOrderLineSDO.setId(forecastOrderLine.getId());
                forecastOrderLineSDO.setDealStatus(forecastOrderLine.getDealStatus());
//                forecastOrderLineSDO.setGmtCreate(forecastOrderLine.getGmtCreate());
//                forecastOrderLineSDO.setGmtModified(forecastOrderLine.getGmtModified());
                forecastOrderLineSDO.setGmtCreate(forecastOrderLine.getGmt_create());
                forecastOrderLineSDO.setGmtModified(forecastOrderLine.getGmt_modified());
                forecastOrderLineSDO.setCreatorId(forecastOrderLine.getCreatorId());
                forecastOrderLineSDO.setModifierId(forecastOrderLine.getModifierId());
                forecastOrderLineSDO.setCreatorName(forecastOrderLine.getCreatorName());
                forecastOrderLineSDO.setModifierName(forecastOrderLine.getModifierName());
                forecastOrderLineSDO.setBizCode(forecastOrderLine.getBizCode());
                forecastOrderLineSDO.setOuterLineId(forecastOrderLine.getOuterLineId());
                forecastOrderLineSDO.setMainOrderId(forecastOrderLine.getMainOrderId());
                forecastOrderLineSDO.setStatus(forecastOrderLine.getStatus());
                forecastOrderLineSDO.setScItemOutCode(forecastOrderLine.getScItemOutCode());
                forecastOrderLineSDO.setCollectStatus(forecastOrderLine.getCollectStatus());
                forecastOrderLineSDO.setAllowCollectAmount(forecastOrderLine.getAllowCollectAmount());
                forecastOrderLineSDO.setCreatorName(forecastOrderLine.getCreatorName());
                forecastOrderLineSDO.setAnalysisReason(forecastOrderLine.getAnalysisReason());
                forecastOrderLineSDO.setAnalysisTime(forecastOrderLine.getAnalysisTime());
                forecastOrderLineSDO.setIdemId(forecastOrderLine.getIdemId());
                forecastOrderLineSDO.setActivityName(forecastOrderLine.getActivityName());
                forecastOrderLineSDO.setActivityCode(forecastOrderLine.getActivityCode());

                Map<String, String> features = (Map) JSONObject.parseObject(forecastOrderLine.getFeatures());
                if (MapUtils.isNotEmpty(features)) {
                    String activityNumber = features.get(ForecastConstants.ACTIVITY_NUMBER);
                    String goodsCode = features.get(ForecastConstants.GOODS_CODE);
                    List<ActivitySDO> activitySDOS = JSONObject.parseArray(JSON.toJSONString(features.get(ForecastConstants.ACTIVITY_DETAILS)), ActivitySDO.class);
                    if (CollectionUtils.isNotEmpty(activitySDOS)) {
                        List<String> collect = activitySDOS.stream().map(ActivitySDO::getActivityTermid).collect(Collectors.toList());
                        activityNumber = collect.stream().collect(Collectors.joining("-"));
                    }
                    forecastOrderLineSDO.setActivityNumber(activityNumber);
                    forecastOrderLineSDO.setGoodsCode(goodsCode);
                    forecastOrderLineSDO.setActivityPriceRemark(features.get(ForecastConstants.ACTIVITY_PRICE_REMARK));
                }
                if (Objects.nonNull(forecastOrderLine.getScItemOutCode())) {
                    forecastOrderLineSDO.setGoodsCode(forecastOrderLine.getScItemOutCode());
                }
                forecastOrderLineSDO.setCustomerCode(forecastOrderLine.getCustomerCode());
                forecastOrderLineSDO.setSerialNumber(forecastOrderLine.getSerialNumber());
                forecastOrderLineSDO.setDepartmentCode(forecastOrderLine.getDepartmentCode());
                forecastOrderLineSDO.setScItemId(forecastOrderLine.getScItemId());
                forecastOrderLineSDO.setScItemTitle(forecastOrderLine.getScItemTitle());
                forecastOrderLineSDO.setPredictReplyAmount(forecastOrderLine.getPredictReplyAmount());
                forecastOrderLineSDO.setQuantity(forecastOrderLine.getQuantity());
                forecastOrderLineSDO.setUnitPrice(forecastOrderLine.getUnitPrice());
                forecastOrderLineSDO.setTotalFee(forecastOrderLine.getTotalFee());
                forecastOrderLineSDO.setActivityPrice(forecastOrderLine.getActivityPrice());
                forecastOrderLineSDO.setTotalActivityFee(forecastOrderLine.getTotalActivityFee());
                forecastOrderLineSDO.setActualTotalReplyAmount(forecastOrderLine.getActualTotalReplyAmount());
                forecastOrderLineSDO.setShouldPayFee(forecastOrderLine.getShouldPayFee());
                forecastOrderLineSDO.setDiscountFee(forecastOrderLine.getDiscountFee());
                forecastOrderLineSDO.setDetailRemark(forecastOrderLine.getDetailRemark());
                forecastOrderLineSDO.setReplyStatus(forecastOrderLine.getReplyStatus());
                forecastOrderLineSDO.setReplyTime(forecastOrderLine.getReplyTime());
                forecastOrderLineSDO.setRefuseReason(forecastOrderLine.getRefuseReason());
                forecastOrderLineSDO.setConfirmTime(forecastOrderLine.getConfirmTime());
                forecastOrderLineSDO.setConfirmStatus(forecastOrderLine.getConfirmStatus());
                forecastOrderLineSDO.setFinishedTime(forecastOrderLine.getFinishedTime());
                forecastOrderLineSDO.setInventoryUnit(forecastOrderLine.getInventoryUnit());
                forecastOrderLineSDO.setInventoryUnitCode(forecastOrderLine.getInventoryUnitCode());
                forecastOrderLineSDO.setSaleUnit(forecastOrderLine.getSaleUnit());
                forecastOrderLineSDO.setSaleUnitCode(forecastOrderLine.getSaleUnitcode());
                forecastOrderLineSDO.setWarehouseArea(forecastOrderLine.getWarehouseArea());
                forecastOrderLineSDO.setUnitConvert(forecastOrderLine.getUnitConvert());
                //target.setGoodsProductationTime(source.getGoodsProductationTime());
                forecastOrderLineSDO.setWarehouseLocation(forecastOrderLine.getWarehouseLocation());
//                forecastOrderLineSDO.setFeatures(JSONObject.parseObject(forecastOrderLine.getFeatures()));
                forecastOrderLineSDO.setSyncVersion(forecastOrderLine.getSyncVersion());
                forecastOrderLineSDO.setTenantId(forecastOrderLine.getTenantId());
                forecastOrderLineSDO.setFeatures(forecastOrderLine.getFeatures() == null ? null : (Map) JSONObject.parseObject(forecastOrderLine.getFeatures()));
                forecastOrderLineSDO.setExt(forecastOrderLine.getExt());
                forecastOrderLineSDO.setExt1(forecastOrderLine.getExt1());
                forecastOrderLineSDO.setExt2(forecastOrderLine.getExt2());
                forecastOrderLineSDO.setExt3(forecastOrderLine.getExt3());
                forecastOrderLineSDO.setExt4(forecastOrderLine.getExt4());
                forecastOrderLineSDO.setExt5(forecastOrderLine.getExt5());

                List<SelectCombox> selectComboxes = new ArrayList<>();
                SelectCombox selectCombox = new SelectCombox();
                if (StringUtils.isNotEmpty(forecastOrderLine.getSaleUnitcode())) {
                    selectCombox.setValue(forecastOrderLine.getSaleUnitcode());
                }
                if (StringUtils.isNotEmpty(forecastOrderLine.getSaleUnit())) {
                    selectCombox.setLabel(forecastOrderLine.getSaleUnit());
                }
                selectComboxes.add(selectCombox);
                forecastOrderLineSDO.setSaleUnitList(selectComboxes);

                return forecastOrderLineSDO;
            }).collect(Collectors.toList());
            //根据行号进行排序
//            forecastOrderLineSDOArrayList.stream().sorted(Comparator.comparing(ForecastOrderLineSDO::getSerialNumber).reversed());
            Collections.sort(forecastOrderLineSDOArrayList, new Comparator<ForecastOrderLineSDO>() {
                @Override
                public int compare(ForecastOrderLineSDO o1, ForecastOrderLineSDO o2) {
                    if (Integer.parseInt(o1.getSerialNumber()) > Integer.parseInt(o2.getSerialNumber())) {
                        return 1;
                    }
                    if (Integer.parseInt(o1.getSerialNumber()) == Integer.parseInt(o2.getSerialNumber())) {
                        return 0;
                    }
                    return -1;
                }
            });
        }
//        for (ForecastOrderLine forecastOrderLine : result) {
//            ForecastOrderLineSDO forecastOrderLineSDO = new ForecastOrderLineSDO();
//            BeanUtils.copyProperties(forecastOrderLine,forecastOrderLineSDO);
//            forecastOrderLineSDOArrayList.add(forecastOrderLineSDO);
////                BeanUtils.copyProperties(forecastOrderLine,forecastOrderLineSDO);
////                forecastOrderLineSDO.setMainOrderId(forecastOrderLine.getId().toString());
////                forecastOrderLineSDO.setStatus(forecastOrderLine.getStatus());
////                forecastOrderLineSDO.setQuantity(forecastOrderLine.getQuantity());
////                forecastOrderLineSDO.setScItemId(forecastOrderLine.getScItemId());
////                forecastOrderLineSDO.setDetailRemark(forecastOrderLine.getDetailRemark());
//        }
        return forecastOrderLineSDOArrayList;
    }

//    /**
//     * 分页查询预售子订单列表  袁登
//     *
//     * @param @return
//     */
////    @Override
////    public PageResult<List<QueryForecastLineResponse>> pageQuery(PageQueryForecastLineRequest pageQueryForecastLineRequest) {
////        QueryForecastOrderLineRequest queryForecastOrderLineRequest = ForecastOrderRepositoryConverter.toQueryForecastOrderLineRequest(pageQueryForecastLineRequest);
////
////        Result<List<OfsForecastOrderLineIndex>> listResult = ofsForecastOrderLineIndexService.queryForecastOrderLine(queryForecastOrderLineRequest);
////        List<QueryForecastLineResponse> collect = Nullable.stream(listResult.getResult()).map(ForecastOrderRepositoryConverter::toQueryForecastLineResponse).collect(Collectors.toList());
////        PageResult<List<QueryForecastLineResponse>> of = PageResult.of(collect, listResult.getTotal());
////        return of;
////    }

    @Override
    @RepositoryInvoker
    public ForecastOrderLineSDO query(String id) {
        LoadForecastOrderLineRequest loadForecastOrderLineRequest = new LoadForecastOrderLineRequest();
        loadForecastOrderLineRequest.setId(id);
        ForecastOrderLine forecastOrderLine = forecastOrderLineService.loadForecastOrderLine(loadForecastOrderLineRequest);
        ForecastOrderLineSDO forecastOrderLineSDO = ForecastOrderRepositoryConverter.toForecastOrderLineSDO(forecastOrderLine);
        return forecastOrderLineSDO;
    }

    /**
     * 根据ids查询子订单列表
     *
     * @param
     * @return
     */
    @Override
    @RepositoryInvoker
    @NotNull
    public PageResult<List<ForecastOrderLineSDO>> batchLoadList(List<String> ids) {
        BatchLoadListRequest forecastOrderLineLoadListRequest = new BatchLoadListRequest();
        forecastOrderLineLoadListRequest.setIds(ids);
        BatchLoadListResponse batchLoadListResponse = forecastOrderLineService.batchLoadList(forecastOrderLineLoadListRequest);
        List<ForecastOrderLineSDO> collect = Nullable.stream(batchLoadListResponse.getResult()).
                map(ForecastOrderRepositoryConverter::toForecastOrderLineSDO).collect(Collectors.toList());

        return PageResult.of(collect, batchLoadListResponse.getResult().size());

    }

    @Override
    @RepositoryInvoker
    public List<ForecastOrderLineSDO> batchForecastOrderLineList(List<String> ids) {
        List<ForecastOrderLine> forecastOrderLines1 = new ArrayList<>();
        for (String id : ids) {
            ForecastOrderLine forecastOrderLineLoadListRequest = new ForecastOrderLine();
            forecastOrderLineLoadListRequest.setId(Long.parseLong(id));
            Result<List<ForecastOrderLine>> listResult = forecastOrderLineService.loadForecastOrderLineList(forecastOrderLineLoadListRequest);
            List<ForecastOrderLine> result = listResult.getResult();
            forecastOrderLines1.addAll(result);
        }
        log.info("明细行行数" + forecastOrderLines1.size());
        BatchLoadListRequest forecastOrderLineLoadListRequest = new BatchLoadListRequest();
        forecastOrderLineLoadListRequest.setIds(ids);
        BatchLoadListResponse batchLoadListResponse = forecastOrderLineService.batchLoadList(forecastOrderLineLoadListRequest);
        List<ForecastOrderLineSDO> collect = Nullable.stream(forecastOrderLines1).map(ForecastOrderRepositoryConverter::toForecastOrderLineSDO).collect(Collectors.toList());
        return collect;

    }

    @Override
    @RepositoryInvoker
    public Result<List<QueryForecastLineResponse>> pageQuery(SearchForecastOrderRequest pageQueryForecastRequest) {
        Integer oriLimit = pageQueryForecastRequest.getLimit();
        // 纪元分页查询， 限制每页返回条数最大是1000条数据， 预报回复页面要返回全部数据
        Result<List<ForecastOrderLineIndex>> forecastOrderLineIndicesResult = queryForecastOrderLines(pageQueryForecastRequest);
        // 获取当前列表中的订单的销售组织列表
        Set<String> organizationCodeList = Sets.newConcurrentHashSet();
        // 货品按照仓库进行分组
        Map<String, Set<String>> itemWarehoseGroup = Maps.newHashMap();
//        Map<String,AllotOrderLineSDO>
        Set<String> allotOrderLineIds = Sets.newConcurrentHashSet();

        List<ForecastOrderLineIndex> forecastOrderLineIndices = forecastOrderLineIndicesResult.getResult();
        for (ForecastOrderLineIndex forecastOrderLineIndex : forecastOrderLineIndices) {
            organizationCodeList.add(forecastOrderLineIndex.getMainOrganizationCode());
            //统计每日库存占用的id
            Map<String, Object> features = JSONObject.parseObject(forecastOrderLineIndex.getSubFeatures());
            if (MapUtils.isNotEmpty(features) && Objects.nonNull(features.get(ForecastConstants.DISINTEGRATION_ALLOT_LINE_ID))) {
                allotOrderLineIds.add(features.get(ForecastConstants.DISINTEGRATION_ALLOT_LINE_ID).toString());
            }
            // 按照仓库将货品分组
            String mainWareHouseCode = forecastOrderLineIndex.getMainWareHouseCode();
            String subScItemId = forecastOrderLineIndex.getSubScItemId();

            Set<String> scItemSets = itemWarehoseGroup.get(mainWareHouseCode);
            if (scItemSets == null) {
                scItemSets = Sets.newHashSet();
                itemWarehoseGroup.put(mainWareHouseCode, scItemSets);
            }
            scItemSets.add(subScItemId);
        }

        // 获取当天提报的预报单数据
        Map<String, Map<String, Integer>> statMap = statTodayForecastOrder(organizationCodeList);
        //批量查询每日库存
        List<String> allotIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(allotOrderLineIds)) {
            allotIds = new ArrayList<>(allotOrderLineIds);
        }
        this.getBelongDailyInventoryList(allotIds);
        // 批量查询库存
        Map<String, Double> inventoryMap = Maps.newHashMap();
        for (Map.Entry<String, Set<String>> entrySet : itemWarehoseGroup.entrySet()) {
            // 获取可用库存
            GetListWarehouseStockRequest getListWarehouseStockRequest = GetListWarehouseStockRequest.builder()
                    .goodsIds(Lists.newArrayList(entrySet.getValue()))
                    .type("1")
                    .warehouseAreaId(entrySet.getKey())
                    .size(entrySet.getValue().size())
                    .page(1).build();

            List<WarehouseInventory> warehouseStockList = forecastOrderQueryRepository.getListWarehouseStock(getListWarehouseStockRequest);
            if (CollectionUtils.isEmpty(warehouseStockList)) {
                continue;
            }

            for (WarehouseInventory warehouseInventory : warehouseStockList) {
                String inventoryKey = String.format("%s-%s", warehouseInventory.getWarehouseAreaId(), warehouseInventory.getGoodsId());
                inventoryMap.put(inventoryKey, Double.parseDouble(warehouseInventory.getAvailableQuantityFormat()));
            }
        }

        List<QueryForecastLineResponse> responses = Lists.newArrayList();
        for (ForecastOrderLineIndex forecastOrderLineIndex : forecastOrderLineIndices) {
            QueryForecastLineResponse queryForecastLineResponse = ForecastOrderRepositoryConverter.toQueryForecastLineResponse(forecastOrderLineIndex);
//            String orderId = queryForecastLineResponse.getFeatures().get("orderId");
//            if (orderId != null){
//                String[] orderIds = orderId.split(",");
//                StringBuilder sb =new StringBuilder();
//                StringBuilder s2 =new StringBuilder();
//                for(int i=0;i<orderIds.length;i++){
//                    OrderQueryRequest queryRequest = new OrderQueryRequest();
//                    queryRequest.setId(orderIds[i]);
//                    Result<OrderQueryResponse> query = orderQueryService.query(queryRequest);
//                    if (query.isSuccess() && query.getResult()!= null){
//                        sb.append(query.getResult().getOrderBizId()).append(",");
//                        s2.append(query.getResult().getCreator()).append(",");
//                    }
//                }
//
//                if (StringUtils.isNotBlank(sb)) {
//                    String saleOrderNo = sb.substring(0, sb.length()-1);
//                    String saleOrderCreatorName = s2.substring(0, s2.length()-1);
//                    //销售单
//                    queryForecastLineResponse.getFeatures().put("saleOrderNo",saleOrderNo);
//                    queryForecastLineResponse.getFeatures().put("saleOrderCreatorName",saleOrderCreatorName);
//                }
//            }
            responses.add(queryForecastLineResponse);

//            QueryResolveInventoryResponse resp = getInventoryByCache(forecastOrderLineIndex);
//            if(resp != null) {
//                String val = Optional.ofNullable(resp.getDailyInventoryMap()).orElse(Maps.newHashMap()).get(forecastOrderLineIndex.getSubScItemId());
//                BigDecimal dailyInventoryCnt = new BigDecimal(StringUtils.defaultIfBlank(val, "0"));
//                String val1 = Optional.ofNullable(resp.getDailyInventoryDeductMap()).orElse(Maps.newHashMap()).get(forecastOrderLineIndex.getSubScItemId());
//                BigDecimal dailyInventoryDeductCnt = new BigDecimal(StringUtils.defaultIfBlank(val1, "0"));
//
//                if((dailyInventoryCnt != null && dailyInventoryCnt.compareTo(BigDecimal.ZERO) > 0) || (dailyInventoryDeductCnt != null && dailyInventoryDeductCnt.compareTo(BigDecimal.ZERO) > 0)) {
//                    queryForecastLineResponse.getFeatures().put("allotQuantity", String.valueOf(dailyInventoryCnt.add( dailyInventoryDeductCnt)));
//                    queryForecastLineResponse.getFeatures().put("allotReaminQuantity", String.valueOf(dailyInventoryCnt));
//                    queryForecastLineResponse.getFeatures().put("allotUsedQuantity", String.valueOf(dailyInventoryDeductCnt));
//                }
//            }
            DailyInventoryLine dailyInventoryLine = getDailyInventoryByCache(forecastOrderLineIndex);
            if (dailyInventoryLine != null) {
                queryForecastLineResponse.getFeatures().put("allotQuantity", trimEndZeroOfBigDecimal(new BigDecimal(dailyInventoryLine.getDistributeQuantity())));
                queryForecastLineResponse.getFeatures().put("allotReaminQuantity", trimEndZeroOfBigDecimal(new BigDecimal(dailyInventoryLine.getRemainQuantity())));
                queryForecastLineResponse.getFeatures().put("allotUsedQuantity", trimEndZeroOfBigDecimal(new BigDecimal(dailyInventoryLine.getSubstractQuantity())));
            }

            if (Objects.nonNull(forecastOrderLineIndex.getMainWareHouseCode())) {
                Double convert = StringUtils.isEmpty(forecastOrderLineIndex.getSubUnitConvert()) ? 1D : Double.parseDouble(forecastOrderLineIndex.getSubUnitConvert());
                // 查询可用库存
                String inventoryKey = String.format("%s-%s", forecastOrderLineIndex.getMainWareHouseCode(), forecastOrderLineIndex.getSubScItemId());
                Double availableInventory = Optional.ofNullable(inventoryMap.get(inventoryKey)).orElse(0D);
                //库存数量解析去除末尾的0值
                queryForecastLineResponse.setAvailableInventory(trimEndZeroOfBigDecimal(BigDecimal.valueOf(availableInventory).setScale(3, RoundingMode.FLOOR)).toString());

                // 当天累计提报量
                String statKey = String.format("%s-%s", forecastOrderLineIndex.getSubScItemId(), forecastOrderLineIndex.getMainOrganizationCode());
                Integer cumulativeQuantityOfForecastReports = Optional.ofNullable(statMap.get(REPORTED_QUANTITY).get(statKey)).orElse(0);
                Double cumulativeQuantityOfForecastReportsDouble = cumulativeQuantityOfForecastReports / convert;
                queryForecastLineResponse.setCumulativeQuantityOfForecastReports(cumulativeQuantityOfForecastReports);

                // 当天累计剩余回复差量
//                String statKey = String.format("%s-%s", forecastOrderLineIndex.getSubScItemId(), forecastOrderLineIndex.getMainOrganizationCode());
                Integer cumulativeQuantityOfForecastRemain = Optional.ofNullable(statMap.get(REMAIN_QUANTITY).get(statKey)).orElse(0);
                Double cumulativeQuantityOfForecastRemainDouble = cumulativeQuantityOfForecastRemain / convert;
//                queryForecastLineResponse.setCumulativeQuantityOfForecastReports(cumulativeQuantityOfForecastRemain);

                // 可用库存 -提报数
                Double availableInventoryOfForecast = Objects.nonNull(availableInventory) ? availableInventory - cumulativeQuantityOfForecastRemainDouble : 0 - cumulativeQuantityOfForecastRemainDouble;
                queryForecastLineResponse.setAvailableInventoryOfForecast(trimEndZeroOfBigDecimal(BigDecimal.valueOf(availableInventoryOfForecast).setScale(3, RoundingMode.FLOOR)).toString());
            }
        }

        List<QueryForecastLineResponse> queryForecastLineResponses = gmtCreateOrderAsc(responses, oriLimit > 200);
        return Result.listSuccess(queryForecastLineResponses, forecastOrderLineIndicesResult.getTotal());
    }

    @Override
    public DailyInventoryLine getDailyInventoryByCache(ForecastOrderLineIndex forecastOrderLineIndex) {

        Map<String, Object> features = JSONObject.parseObject(forecastOrderLineIndex.getSubFeatures());
        if (MapUtils.isEmpty(features) || Objects.isNull(features.get(ForecastConstants.DISINTEGRATION_ALLOT_LINE_ID))) {
            return null;
        }
        String cacheKey = ForecastConstants.DISINTEGRATION_ALLOT_CATCH_ + features.get(ForecastConstants.DISINTEGRATION_ALLOT_LINE_ID);

        DailyInventoryLine resp = dailyInventoryCache.getIfPresent(cacheKey);
        if (resp == null) {
            List<DailyInventoryLine> dailyInventory = getBelongDailyInventoryList(Lists.newArrayList(features.get(ForecastConstants.DISINTEGRATION_ALLOT_LINE_ID).toString()));
            if (CollectionUtils.isNotEmpty(dailyInventory)) {
                resp = dailyInventory.get(0);
            }
            if (resp != null) {
                dailyInventoryCache.put(cacheKey, resp);
            }
        }
        return resp;
    }

    //批量获取每日库存数据，并缓存下来
    private List<DailyInventoryLine> getBelongDailyInventoryList(List<String> request) {
        if (CollectionUtils.isEmpty(request)) {
            return new ArrayList<>();
        }
        QueryDailyAllotOrderLine queryDailyAllotOrderLine = new QueryDailyAllotOrderLine();
        queryDailyAllotOrderLine.setAllotLineIdList(request);
        Result<List<DailyInventoryLine>> dailys = inventoryAllotQueryService.queryAllotOrderLineById(queryDailyAllotOrderLine);
        if (dailys != null && CollectionUtils.isNotEmpty(dailys.getResult())) {
            dailys.getResult().forEach(dailyInventoryLine -> {
                dailyInventoryCache.put(ForecastConstants.DISINTEGRATION_ALLOT_CATCH_ + dailyInventoryLine.getLineId(), dailyInventoryLine);
            });
            return dailys.getResult();
        }
        return new ArrayList<>();
    }


    @Override
    public QueryResolveInventoryResponse getInventoryByCache(ForecastOrderLineIndex forecastOrderLineIndex) {

        String subScItemId = forecastOrderLineIndex.getSubScItemId();
        String mainChannelCode = forecastOrderLineIndex.getMainChannelCode();
        String mainDepartmentCode = forecastOrderLineIndex.getMainDepartmentCode();
        String mainOrganizationCode = forecastOrderLineIndex.getMainOrganizationCode();
        String mainSaleChannelCode = forecastOrderLineIndex.getMainSaleChannelCode();
        String mainSalesmanCode = forecastOrderLineIndex.getMainSalesmanId();

        String cacheKey = String.format("%s-%s-%s-%s-%s-%s", mainOrganizationCode, mainChannelCode, mainDepartmentCode, mainSaleChannelCode, mainSalesmanCode, subScItemId);

        QueryResolveInventoryResponse resp = inventoryCache.getIfPresent(cacheKey);
        if (resp == null) {
            resp = getAccumulateQuantityOfForecast(forecastOrderLineIndex);
            if (resp != null) {
                inventoryCache.put(cacheKey, resp);
            } else {
                inventoryCache.put(cacheKey, new QueryResolveInventoryResponse());
            }
        }
        return resp;
    }

    @Override
    public ForecastOrderLineIndex getForecastOrderLineIndex(ForecastOrderLineSDO forecastOrderLineSDO) {
        SearchForecastOrderRequest pageQueryForecastRequest = new SearchForecastOrderRequest();
        pageQueryForecastRequest.setSubLineBizId(Lists.newArrayList(forecastOrderLineSDO.getId() + ""));
        pageQueryForecastRequest.setStart(0);
        pageQueryForecastRequest.setLimit(1);
        Result<List<ForecastOrderLineIndex>> resp = forecastOrderLineIndexService.queryForecastOrderLineByEs(pageQueryForecastRequest);
        if (resp != null && CollectionUtils.isNotEmpty(resp.getResult())) {
            return resp.getResult().get(0);
        }
        return null;
    }

    @NotNull
    //当天累计剩余回复数量
    private Map<String, Map<String, Integer>> statTodayForecastOrder(Set<String> organizationCodeList) {
        if (CollectionUtils.isEmpty(organizationCodeList)) {
            return Maps.newConcurrentMap();
        }
        Map<String, Map<String, Integer>> statics = new HashMap<>();
        //当天累计提报数量
        Map<String, Integer> statMap = Maps.newConcurrentMap();
        //当天累计剩余回复数量
        Map<String, Integer> statRemainMap = Maps.newConcurrentMap();
        SearchForecastOrderRequest queryTodayForecastRequest = new SearchForecastOrderRequest();
        queryTodayForecastRequest.setLimit(100000);
        queryTodayForecastRequest.setValidStartDate(DateUtils.getFirstTime(new Date()));
        queryTodayForecastRequest.setValidEndDate(DateUtils.getLatestTime(new Date()));
        queryTodayForecastRequest.setOrganizationCodeList(Lists.newArrayList(organizationCodeList));
        // 统计当日 待回复，部分回复， 已完成的预报单
        queryTodayForecastRequest.setDetailStatusList(Lists.newArrayList(2, 3, 4));
        queryTodayForecastRequest.setMainStatusList(Lists.newArrayList(2,3,4));
        Result<List<ForecastOrderLineIndex>> forecastOrderLineIndicesResult = queryForecastOrderLines(queryTodayForecastRequest);
        List<ForecastOrderLineIndex> forecastOrderLineIndices = forecastOrderLineIndicesResult.getResult();
        for (ForecastOrderLineIndex todayForecastOrderLineIndex : forecastOrderLineIndices) {
            if(StringUtils.isNotBlank(todayForecastOrderLineIndex.getSubRefuseReasonCode())) {
                continue;
            }

            String scItemId = todayForecastOrderLineIndex.getSubScItemId();
            String orgCode = todayForecastOrderLineIndex.getMainOrganizationCode();

            Long replyQuantity = todayForecastOrderLineIndex.getSubActualTotalReplyAmount() == null ? 0L : todayForecastOrderLineIndex.getSubActualTotalReplyAmount();
            Long quantityStr = StringUtils.isEmpty(todayForecastOrderLineIndex.getSubQuantity()) ? 0L : Long.parseLong(todayForecastOrderLineIndex.getSubQuantity());

            String key = String.format("%s-%s", scItemId, orgCode);
//            int quantity = quantityStr.intValue() - replyQuantity.intValue();
            int remainQuantity = quantityStr.intValue() - replyQuantity.intValue();
            if (statMap.containsKey(key)) {
                statMap.put(key, statMap.get(key) + quantityStr.intValue());
                statRemainMap.put(key, statRemainMap.get(key) + remainQuantity);
            } else {
                statMap.put(key, quantityStr.intValue());
                statRemainMap.put(key, remainQuantity);
            }
        }
        statics.put(REPORTED_QUANTITY, statMap);
        statics.put(REMAIN_QUANTITY, statRemainMap);
        return statics;
    }

    public static void main(String[] args) {
        Long a = 10000L;
        Long b = 100L;

        int i = a.intValue() - b.intValue();

        System.out.println(a.intValue());
        System.out.println(b.intValue());
    }

    @RepositoryInvoker
    private Result<List<ForecastOrderLineIndex>> queryForecastOrderLines(SearchForecastOrderRequest pageQueryForecastRequest) {
        // 分页查询
        if (pageQueryForecastRequest.getStart() != null && pageQueryForecastRequest.getLimit() != null && pageQueryForecastRequest.getLimit() < 200) {
            return forecastOrderLineIndexService.queryForecastOrderLineByEs(pageQueryForecastRequest);
        }

        // 查全量
        Integer oriLimit = pageQueryForecastRequest.getLimit();
        // 1.获取总数量
        int total = 0;
        int limit = 200;
        pageQueryForecastRequest.setStart(0);
        pageQueryForecastRequest.setLimit(limit);
        Result<List<ForecastOrderLineIndex>> listResult = forecastOrderLineIndexService.queryForecastOrderLineByEs(pageQueryForecastRequest);
        if (listResult != null) {
            total = listResult.getTotal();
        }

        if (total <= limit) {
            return listResult;
        }

        // 通过传参控制下数据量
        total = total > oriLimit ? oriLimit : total;

        // 并行获取所有页的数据
        List<Future<List<ForecastOrderLineIndex>>> collect = Lists.newArrayList();
        List<ForecastOrderLineIndex> forecastOrderLineIndices = Lists.newArrayList();
        int totalPage = total % limit == 0 ? total / limit : total / limit + 1;
        for (int i = 0; i < totalPage; i++) {
            int finalI = i;
            CompletableFuture<List<ForecastOrderLineIndex>> future = CompletableFuture.supplyAsync(() -> {
                SearchForecastOrderRequest tmpReq = new SearchForecastOrderRequest();
                BeanUtils.copyProperties(pageQueryForecastRequest, tmpReq);
                tmpReq.setStart(finalI * limit);
                tmpReq.setLimit(limit);
                Result<List<ForecastOrderLineIndex>> tmpResult = forecastOrderLineIndexService.queryForecastOrderLineByEs(tmpReq);
                if (tmpResult != null && CollectionUtils.isNotEmpty(tmpResult.getResult())) {
                    return tmpResult.getResult();
                }
                return Lists.newArrayList();
            }, scItemsQueryTaskExecutor);

            collect.add(future);
        }

        for (Future<List<ForecastOrderLineIndex>> listFuture : collect) {
            try {
                forecastOrderLineIndices.addAll(listFuture.get());
            } catch (Exception e) {
                // ignore
            }
        }

        listResult.setResult(forecastOrderLineIndices);
        return listResult;
    }

    private Long getForecastOrderImportIndex(QueryForecastLineResponse o1) {
        if (o1 == null || MapUtils.isEmpty(o1.getFeatures())) {
            return Long.MAX_VALUE;
        }

        Object importIndex = o1.getFeatures().getOrDefault(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, "");
        String indexNum = StringUtils.replace(importIndex.toString(), "_", "");
        return NumberUtils.toLong(indexNum, Long.MAX_VALUE);
    }

    private QueryResolveInventoryResponse getAccumulateQuantityOfForecast(ForecastOrderLineIndex forecastOrderLineIndex) {
        String subScItemId = forecastOrderLineIndex.getSubScItemId();
        BatchQueryAllotRequest batchQueryAllotRequest = new BatchQueryAllotRequest();
        batchQueryAllotRequest.setChannelCode(forecastOrderLineIndex.getMainChannelCode());
        batchQueryAllotRequest.setDepartmentCode(forecastOrderLineIndex.getMainDepartmentCode());
        batchQueryAllotRequest.setOrganizationCode(forecastOrderLineIndex.getMainOrganizationCode());
        batchQueryAllotRequest.setSaleChannelCode(forecastOrderLineIndex.getMainSaleChannelCode());
        batchQueryAllotRequest.setSalesmanCode(forecastOrderLineIndex.getMainSalesmanId());
        batchQueryAllotRequest.setScItemList(Arrays.asList(subScItemId));
        Result<QueryResolveInventoryResponse> result = inventoryAllotQueryService.batchQueryAllot(batchQueryAllotRequest);
        if (Objects.nonNull(result) && Objects.nonNull(result.getResult())
                && Objects.nonNull(result.getResult().getDailyInventoryMap())
                && Objects.nonNull(result.getResult().getDailyInventoryMap().get(subScItemId))) {
            return result.getResult();
        }
        return null;
    }

    public List<QueryForecastLineResponse> gmtCreateOrderAsc(List<QueryForecastLineResponse> forecastList, boolean importSort) {
        if(importSort) {
            Collections.sort(forecastList, Comparator.comparing(this::getForecastOrderImportIndex));
            return forecastList;
        } else {
            Collections.sort(forecastList, Comparator.comparing(o -> Long.valueOf(Optional.ofNullable(o.getMainOrderId()).orElse("0"))));
            return forecastList;
        }
    }


    private Integer getPredictReplyAmount(ForecastOrderSDO forecastOrderSDO, ForecastOrderLineSDO forecastOrderLineSDO) {
        return 100;
    }

    public Long getPrice(ForecastOrderSDO forecastOrderSDO, ForecastOrderLineSDO forecastOrderLineSDO) {
        //一 获取价格
        PriceQueryRequest priceQueryRequest = new PriceQueryRequest();
        List<DimensionPropertyInfoRequest> DimensionPropertyInfoList = new ArrayList<>();
        DimensionPropertyInfoRequest dimensionPropertyInfoRequest = new DimensionPropertyInfoRequest();
        dimensionPropertyInfoRequest.setPriceTypeId("ZP01");//价格类型
        dimensionPropertyInfoRequest.setPriceUseDate(new Date());//价格使用时间
        //场地的信息
        PlaceInfoRequest placeInfoRequest = PlaceInfoRequest.builder()
                .orgSalesOrganizationCode(forecastOrderSDO.getOrganizationCode())//销售组织
                //                    .orgSalesOrganizationCode("6140")//销售组织
                .channelCode(forecastOrderSDO.getChannelCode())//业务渠道code
                //                    .salesUnitCode(forecastOrderLineSDO.getSaleUnit())//销售单位code
                .salesUnitCode("GUA")//销售单位code
                .salesArea("")//销售地区编码
                .factoryCode("")//工厂编码
                .departmentCode(forecastOrderSDO.getDepartmentCode())//销售部门
                .priceArea("")//定价区域
                .build();
        dimensionPropertyInfoRequest.setPlaceInfoRequest(placeInfoRequest);
        //货的信息
        MaterialInfoRequest materialInfoRequest = new MaterialInfoRequest();
        materialInfoRequest.setMaterialCode(forecastOrderLineSDO.getScItemId());//货品编码（ SAP物料编码）
//            materialInfoRequest.setScItemGroupCode(forecastOrderSDO.getProductGroupCode());//产品组编码
        materialInfoRequest.setScItemGroupCode("11");//产品组编码 货品组
        dimensionPropertyInfoRequest.setMaterialInfoRequest(materialInfoRequest);
        // 人的信息
        HumanInfoRequest humanInfoRequest = new HumanInfoRequest();
        humanInfoRequest.setCustomerCode(forecastOrderSDO.getCustomerCode());//客户编码
        humanInfoRequest.setCustomerSaleAddressCode(forecastOrderSDO.getWareHouseCode());//售达方编码 客户编码（SAP售达方编码）
        humanInfoRequest.setCustomerGroup("");//客户组
        humanInfoRequest.setCustomerSendAddressCode(forecastOrderSDO.getReceiveAddressCode());//客户收货地址编码（SAP 送达方编码）
//                humanInfoRequest.setCustomerSendAddressCode("3730300301");//客户收货地址编码（SAP 送达方编码）
        humanInfoRequest.setPriceListCode("");//价目清单编码 (从客户信息上取)
        dimensionPropertyInfoRequest.setHumanInfoRequest(humanInfoRequest);
        //添加维度
        DimensionPropertyInfoList.add(dimensionPropertyInfoRequest);
        priceQueryRequest.setDimensionPropertyInfoRequestList(DimensionPropertyInfoList);
        Result<PriceQueryResponse> priceQueryResponseResult = priceQueryService.batchQueryPrice(priceQueryRequest);
        if (priceQueryResponseResult.isSuccess() || priceQueryResponseResult.getResult() == null) {
            return 0L;
        }
        List<ItemPriceResponse> itemPriceResponseList = priceQueryResponseResult.getResult().getItemPriceResponseList();
        ItemPriceResponse itemPriceResponse = itemPriceResponseList.get(0);
        Long moneyAmout = itemPriceResponse.getMoneyAmout();
        return moneyAmout;
    }

    @Override
    public ForecastOrderSDO queryByOrderId(ForecastOrderSDO forecastOrderSDO) {
        ForecastOrderLine forecastOrderLineLoadListRequest = new ForecastOrderLine();
        forecastOrderLineLoadListRequest.setMainOrderId(forecastOrderSDO.getId());
        Result<List<ForecastOrderLine>> listResult = forecastOrderLineService.loadForecastOrderLineList(forecastOrderLineLoadListRequest);
        List<ForecastOrderLine> forecastOrderLines = listResult.getResult();
        List<ForecastOrderLineSDO> forecastOrderLineSDOList = new ArrayList<>();
        for (Object obj : forecastOrderLines) {
            ForecastOrderLine forecastOrderLine = JSONObject.parseObject(JSONObject.toJSONString(obj), ForecastOrderLine.class);
            ForecastOrderLineSDO forecastOrderLineSDO = new ForecastOrderLineSDO();
            forecastOrderLineSDO.setId(forecastOrderLine.getId());
            forecastOrderLineSDO.setStatus(forecastOrderLine.getStatus());
            forecastOrderLineSDO.setFeatures(JSONObject.parseObject(forecastOrderLine.getFeatures()));
            forecastOrderLineSDO.setQuantity(forecastOrderLine.getQuantity());
            forecastOrderLineSDO.setSerialNumber(forecastOrderLine.getSerialNumber());
            forecastOrderLineSDO.setScItemId(forecastOrderLine.getScItemId());
            forecastOrderLineSDO.setUnitConvert(forecastOrderLine.getUnitConvert());
            forecastOrderLineSDO.setGoodsCode(forecastOrderLine.getScItemOutCode());
            forecastOrderLineSDOList.add(forecastOrderLineSDO);
        }
        forecastOrderSDO.setForecastOrderLineSDOList(forecastOrderLineSDOList);

        return forecastOrderSDO;
    }

    /**
     * 根据处理状态查询子订单
     *
     * @param dealStatus
     * @return
     */
    @Override
    public PageResult<List<ForecastOrderLineSDO>> queryListByDealStatus(List<Integer> dealStatus) {
        LoadListByDealStatusRequest loadListByDealStatusRequest = new LoadListByDealStatusRequest();
        loadListByDealStatusRequest.setDealStatusList(dealStatus);
        LoadListByDealStatusResponse batchLoadListResponse = new LoadListByDealStatusResponse();
        try {
            batchLoadListResponse = forecastOrderLineService.loadListByDealStatus(loadListByDealStatusRequest);
        } catch (Exception e) {
            log.error("查询异常", e);
        }
        List<ForecastOrderLineSDO> collect = Nullable.stream(batchLoadListResponse.getResult()).map(ForecastOrderRepositoryConverter::toForecastOrderLineSDO).collect(Collectors.toList());
        List<ForecastOrderLineSDO> collect1 = Nullable.stream(collect).sorted(Comparator.comparing(ForecastOrderLineSDO::getId).reversed()).collect(Collectors.toList());
        return PageResult.of(collect1, batchLoadListResponse.getResult().size());
    }

    //库存数量解析去除末尾的0值
    private String trimEndZeroOfBigDecimal(BigDecimal bigDecimal) {
        String val = "";
        if (bigDecimal == null) {
            return val;
        } else {
            val = String.valueOf(bigDecimal);
        }
        if (val.indexOf(".") > 0) {
            // 去掉后面无用的零
            val = val.replaceAll("0+?$", "");
            // 如小数点后面全是零则去掉小数点
            val = val.replaceAll("[.]$", "");
        }
        return val;
    }


    @Override
    public List<DealForecastOrderResponse> loadDealForecastListV2(DealForecastListRequest dealForecastListRequest) {
        List<DealForecastOrderResponse> dealForecastOrderResponses = new CopyOnWriteArrayList<>();
        //nowIds是主单id，新版本v2不用该字段
        //ids页面选中的子单id
        List<String> orderLineIds = dealForecastListRequest.getIds().stream().map(String::valueOf).collect(Collectors.toList());

        //根据当前日期的单据主单Id 查询出所有的子单
//        List<String> nowLineIds = dealForecastListRequest.getNowLineIds();
        // 货品按照仓库进行分组
        Map<String, Set<String>> itemWarehouseGroup = Maps.newHashMap();
        SearchForecastOrderRequest queryTodayForecastRequest = new SearchForecastOrderRequest();
        queryTodayForecastRequest.setLimit(100000);
        queryTodayForecastRequest.setGmtStartCreate(DateUtils.getFirstTime(new Date()));
        queryTodayForecastRequest.setGmtEndCreate(DateUtils.getLatestTime(new Date()));
        // 统计当日 待回复，部分回复， 已完成的预报单
        queryTodayForecastRequest.setDetailStatusList(Lists.newArrayList(2, 3, 4));
        Result<List<ForecastOrderLineIndex>> forecastOrderLineIndicesResult = queryForecastOrderLines(queryTodayForecastRequest);

        //当天累计剩余回复数量
        Map<String, Integer> remainReplyCntMap = Maps.newConcurrentMap();
//        //主单IDs
//        Set<String> mainOrderIds = Sets.newHashSet();
        //主单id/客户信贷信息
        Map<String, ForecastOrderLineIndex> mainOrderMap = Maps.newConcurrentMap();
        List<ForecastOrderLineIndex> forecastOrderLineIndices = forecastOrderLineIndicesResult.getResult();
        for (ForecastOrderLineIndex todayForecastOrderLineIndex : forecastOrderLineIndices) {
            //当天累计剩余回复数量
            String scItemId = todayForecastOrderLineIndex.getSubScItemId();
            String wareHouseAreaId = todayForecastOrderLineIndex.getMainWareHouseCode();
            Long replyQuantity = todayForecastOrderLineIndex.getSubActualTotalReplyAmount() == null ? 0L : todayForecastOrderLineIndex.getSubActualTotalReplyAmount();
            Long quantityStr = StringUtils.isEmpty(todayForecastOrderLineIndex.getSubQuantity()) ? 0L : Long.parseLong(todayForecastOrderLineIndex.getSubQuantity());

            String key = String.format("%s-%s", wareHouseAreaId, scItemId);
//            int quantity = quantityStr.intValue() - replyQuantity.intValue();
            int remainQuantity = quantityStr.intValue() - replyQuantity.intValue();
            if (remainReplyCntMap.containsKey(key)) {
                remainReplyCntMap.put(key, remainReplyCntMap.get(key) + remainQuantity);
            } else {
                remainReplyCntMap.put(key, remainQuantity);
            }
        }
        SearchForecastOrderRequest selectQuery = new SearchForecastOrderRequest();
        selectQuery.setLimit(100000);
        selectQuery.setSubLineBizId(orderLineIds);
        Result<List<ForecastOrderLineIndex>> selectedForecastOrderLines = queryForecastOrderLines(selectQuery);
        if (selectedForecastOrderLines == null || CollectionUtils.isEmpty(selectedForecastOrderLines.getResult())) {
            return dealForecastOrderResponses;
        }

        for (ForecastOrderLineIndex todayForecastOrderLineIndex : selectedForecastOrderLines.getResult()) {
            //选中的主子单
            if (!mainOrderMap.containsKey(todayForecastOrderLineIndex.getSubMainOrderId())) {

                mainOrderMap.put(todayForecastOrderLineIndex.getSubMainOrderId(), todayForecastOrderLineIndex);
            }

            // //选中的主子单 按照仓库将货品分组
            String mainWareHouseCode = todayForecastOrderLineIndex.getMainWareHouseCode();
            String subScItemId = todayForecastOrderLineIndex.getSubScItemId();

            Set<String> scItemSets = itemWarehouseGroup.get(mainWareHouseCode);
            if (scItemSets == null) {
                scItemSets = Sets.newHashSet();
                itemWarehouseGroup.put(mainWareHouseCode, scItemSets);
            }
            scItemSets.add(subScItemId);
        }


        // 批量获取主单 & 客户信贷信息
        Map<String, Long> mainOrderCreditMap = Maps.newConcurrentMap();
        List<CompletableFuture<Pair<String, Long>>> creditFeatures = Lists.newCopyOnWriteArrayList();
        for (ForecastOrderLineIndex forecastOrderLineIndex : mainOrderMap.values()) {
            // TODO: 2021/12/23 优化信贷查询的性能 接口有改为批量方法吗
            CompletableFuture<Pair<String, Long>> future = CompletableFuture.supplyAsync(() -> {
                String organizationCode = forecastOrderLineIndex.getMainOrganizationCode();
                String customerCode = forecastOrderLineIndex.getMainCustomerCode();
                String channelCode = forecastOrderLineIndex.getMainChannelCode();
                String itemGroupCode = forecastOrderLineIndex.getMainProductGroupCode();
                QueryCreditRequest request = new QueryCreditRequest();
                request.setOrganizationCode(organizationCode);
                request.setChannelCode(channelCode);
                request.setItemGroupCode(itemGroupCode);
                request.setCustomerCode(customerCode);
                request.setSaleOrderId(forecastOrderLineIndex.getSubMainOrderId());

                String creditKey = String.format("%s-%s-%s-%s", organizationCode, customerCode, channelCode, itemGroupCode);

                Long creditCnt = queryCustomerCredit(request);

                return Pair.create(creditKey, creditCnt);

            }, scItemsQueryTaskExecutor);

            creditFeatures.add(future);
        }

        // 批量查询库存
        Map<String, Double> inventoryMap = Maps.newHashMap();
        for (Map.Entry<String, Set<String>> entrySet : itemWarehouseGroup.entrySet()) {
            // 获取可用库存
            GetListWarehouseStockRequest getListWarehouseStockRequest = GetListWarehouseStockRequest.builder()
                    .goodsIds(Lists.newArrayList(entrySet.getValue()))
                    .type("1")
                    .warehouseAreaId(entrySet.getKey())
                    .size(entrySet.getValue().size())
                    .page(1).build();

            List<WarehouseInventory> warehouseStockList = forecastOrderQueryRepository.getListWarehouseStock(getListWarehouseStockRequest);
            if (org.apache.commons.collections.CollectionUtils.isEmpty(warehouseStockList)) {
                continue;
            }

            for (WarehouseInventory warehouseInventory : warehouseStockList) {
                String inventoryKey = String.format("%s-%s", warehouseInventory.getWarehouseAreaId(), warehouseInventory.getGoodsId());
                inventoryMap.put(inventoryKey, Double.parseDouble(warehouseInventory.getAvailableQuantityFormat()));
            }
        }

        // 获取信贷信息
        for (CompletableFuture<Pair<String, Long>> creditFeature : creditFeatures) {
            Pair<String, Long> credit = null;
            try {
                // 信贷接口设置1秒的超时时间， 失败直接降级掉
                credit = creditFeature.get(2, TimeUnit.SECONDS);
            } catch (Exception e) {
                log.error("信贷查询失败", e);
            }

            if (credit != null && credit.getKey() != null && credit.getValue() != null) {
                mainOrderCreditMap.put(credit.getKey(), credit.getValue());
            }
        }

        Map<Long, DealForecastOrderResponse> dealForecastOrderResponseMap = new ConcurrentHashMap<>();
        Map<Long, CompletableFuture<Integer>> dealForecastOrderResponsesFutures = new ConcurrentHashMap<>();
        for (ForecastOrderLineIndex lineIndex : selectedForecastOrderLines.getResult()) {
//            ForecastOrderLineIndex forecastOrderSDO = mainOrderMap.get(lineIndex.getSubMainOrderId());
            String inventoryKey = String.format("%s-%s", lineIndex.getMainWareHouseCode(), lineIndex.getSubScItemId());
//            String remainKey = String.format("%s-%s", forecastOrderSDO.getMainWareHouseCode(), lineIndex.getSubScItemId());
            String remainKey = String.format("%s-%s", lineIndex.getMainWareHouseCode(), lineIndex.getSubScItemId());
            Integer remainCnt = remainReplyCntMap.get(remainKey);
            Double inventoryCnt = inventoryMap.get(inventoryKey);
            //信贷
            String organizationCode = lineIndex.getMainOrganizationCode();
            String customerCode = lineIndex.getMainCustomerCode();
            String channelCode = lineIndex.getMainChannelCode();
            String productGroupCode = lineIndex.getMainProductGroupCode();
            String creditKey = String.format("%s-%s-%s-%s", organizationCode, customerCode, channelCode, productGroupCode);
            Long creditCnt = mainOrderCreditMap.get(creditKey);
            DealForecastOrderResponse dealForecastOrderResponse = convert2DealForecastOrderResponseByIndex(lineIndex, remainCnt, inventoryCnt, creditCnt);
            dealForecastOrderResponses.add(dealForecastOrderResponse);
            dealForecastOrderResponseMap.put(lineIndex.getSubId(), dealForecastOrderResponse);

            //月度计划
            CompletableFuture<Integer> dealForecastOrderResponseFuture = CompletableFuture.supplyAsync(() -> {
                //计划差量
                /**
                 * 1、获取该客户的本月累计月度计划回复数量
                 * 2、计算本月销售订单的累计出库数量
                 * 3、该值=1-2
                 * 4、不可编辑
                 */
                //根据固定条件获取客户地址唯一id
                //计划量和发货数量的差量
                Integer planDifferenceQuantity = this.getPlanDifferenceQuantity(lineIndex);
                return planDifferenceQuantity;
            }, scItemsQueryTaskExecutor);

            dealForecastOrderResponsesFutures.put(lineIndex.getSubId(), dealForecastOrderResponseFuture);
        }

        for (Map.Entry<Long, CompletableFuture<Integer>> entry : dealForecastOrderResponsesFutures.entrySet()) {
            DealForecastOrderResponse resp = dealForecastOrderResponseMap.get(entry.getKey());
            Integer planVariance = null;
            try {
                planVariance = entry.getValue().get(2, TimeUnit.SECONDS);
            } catch (Exception e) {
                log.info("获取计划差量失败", e);
            }
            resp.setPlanVariance(planVariance);
        }

        return dealForecastOrderResponses;
    }

    // 此方法若与0925分支发生冲突，以bugfix分支为准。（0925分支代码会删掉）
    // 拷贝loadDealForecastListV2 去除库存、信贷、月度计划等查询
    @Override
    public List<DealForecastOrderResponse> loadDealForecastListV3(DealForecastListRequest dealForecastListRequest) {
        List<DealForecastOrderResponse> dealForecastOrderResponses = new CopyOnWriteArrayList<>();
        //nowIds是主单id，新版本v2不用该字段
        //ids页面选中的子单id
        List<String> orderLineIds = dealForecastListRequest.getIds().stream().map(String::valueOf).collect(Collectors.toList());

        SearchForecastOrderRequest selectQuery = new SearchForecastOrderRequest();
        selectQuery.setLimit(100000);
        selectQuery.setSubLineBizId(orderLineIds);
        Result<List<ForecastOrderLineIndex>> selectedForecastOrderLines = queryForecastOrderLines(selectQuery);
        if (selectedForecastOrderLines == null || CollectionUtils.isEmpty(selectedForecastOrderLines.getResult())) {
            return dealForecastOrderResponses;
        }

        for (ForecastOrderLineIndex lineIndex : selectedForecastOrderLines.getResult()) {
            DealForecastOrderResponse dealForecastOrderResponse = convert2DealForecastOrderResponseByIndex(lineIndex, null, null, null);
            dealForecastOrderResponses.add(dealForecastOrderResponse);
        }

        return dealForecastOrderResponses;
    }

    @Override
    public Result<List<ForecastOrderLineIndex>> queryForecastOrderLinesForReport(SearchForecastOrderRequest pageQueryForecastRequest) {
        // 分页查询
        if (pageQueryForecastRequest.getStart() != null && pageQueryForecastRequest.getLimit() != null && pageQueryForecastRequest.getLimit() < 500) {
            return forecastOrderLineIndexService.queryForecastOrderLineByEsForReport(pageQueryForecastRequest);
        }

        int limit = 500;
        SearchForecastOrderRequest totalRequest = new SearchForecastOrderRequest();
        totalRequest.setMainBisUnitCode(pageQueryForecastRequest.getMainBisUnitCode());
        totalRequest.setValidStartDate(pageQueryForecastRequest.getValidStartDate());
        totalRequest.setValidEndDate(pageQueryForecastRequest.getValidEndDate());
        totalRequest.setStart(0);
        totalRequest.setLimit(1);
        Result<List<ForecastOrderLineIndex>> totalResult = forecastOrderLineIndexService.queryForecastOrderLineByEsForReport(totalRequest);
        int totalCnt = totalResult.getTotal();
        int totalPage = totalCnt / limit;
        if (totalCnt%limit >0){
            totalPage++;
        }

        List<Future< List<ForecastOrderLineIndex>>> futureList = Lists.newArrayList();
        for (int pageNo = 0; pageNo < totalPage; pageNo++) {
            int start = pageNo*limit;
            CompletableFuture<List<ForecastOrderLineIndex>> future = CompletableFuture.supplyAsync(() -> {
                SearchForecastOrderRequest request = new SearchForecastOrderRequest();
                request.setMainBisUnitCode(pageQueryForecastRequest.getMainBisUnitCode());
                request.setValidStartDate(pageQueryForecastRequest.getValidStartDate());
                request.setValidEndDate(pageQueryForecastRequest.getValidEndDate());
                request.setStart(start);
                request.setLimit(limit);
                Result<List<ForecastOrderLineIndex>> listResult = null;
                try {
                    listResult = forecastOrderLineIndexService.queryForecastOrderLineByEsForReport(request);
                    if (listResult==null || CollectionUtils.isEmpty(listResult.getResult())){
                        return Lists.newArrayList();
                    }
                } catch (Exception e) {
                    log.error("多线程拉取预报订单数据异常", e);
                }
                List<ForecastOrderLineIndex> list = listResult.getResult();
                return list;
            }, forecastSaleTaskExecutor);
            futureList.add(future);
        }
        List<ForecastOrderLineIndex> result = new ArrayList<>();
        try {
            for (Future< List<ForecastOrderLineIndex>> future : futureList){
                List<ForecastOrderLineIndex> subList = future.get();
                result.addAll(subList);
            }
        }catch (Exception e){
            log.error("获取多线程查询结果异常", e);
        }
        return Result.listSuccess(result,result.size());
    }

    private Integer getPlanDifferenceQuantity(ForecastOrderLineIndex forecastOrderLineIndex) {
        int planDifferenceQuantity = 0;
        try {
            /**
             * 查询客户地址Id
             */
            PageQueryAddressListRequest pageQueryAddressListRequest = PageQueryAddressListRequest.builder()
                    .addressCode(forecastOrderLineIndex.getMainReceiveAddressCode())
                    .channelCode(forecastOrderLineIndex.getMainChannelCode())
                    .customerCode(forecastOrderLineIndex.getMainCustomerCode())
                    .orgSaleOrganizationCode(forecastOrderLineIndex.getMainOrganizationCode())
                    .itemGroup(forecastOrderLineIndex.getMainProductGroupCode())
                    .build();
            String addressSDOId = "";
            log.info("查询客户地址Id参数", pageQueryAddressListRequest);
            PageQueryAddressListResponse pageQueryAddressListResponse = otsPlatformEnhanceService.pageQueryAddressList(pageQueryAddressListRequest);
            if (Objects.nonNull(pageQueryAddressListResponse) && org.apache.commons.collections4.CollectionUtils.isNotEmpty(pageQueryAddressListResponse.getResult())) {
                List<CustomerAddressSDO> result1 = pageQueryAddressListResponse.getResult();
                CustomerAddressSDO customerAddressSDO = result1.get(0);
                addressSDOId = customerAddressSDO.getId();
            } else {
                throw new FunctionException("OTS-04-001-00-15-034");
            }


            /**
             * 查询月度计划planId
             */
            PageQuerySalePlanRequest pageQuerySalePlanRequest = new PageQuerySalePlanRequest();
            /*String date = com.alibaba.citrus.ots.common.util.DateUtils.formatDate(new Date(), "yyyy-MM-dd");
            pageQuerySalePlanRequest.setPlanTime(date);*/
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH) + 1;
            pageQuerySalePlanRequest.setPlanTime(year + "-" + month);
            pageQuerySalePlanRequest.setOrgBusinessUnitCode(forecastOrderLineIndex.getMainBisUnitCode());
            pageQuerySalePlanRequest.setLimit(1);
            String planId = "";
            log.info("查询月度计划PlanId参数", pageQuerySalePlanRequest);
            Result<PageResult<List<SalesPlanSDO>>> pageResultResult = salesPlanQueryService.pageQuerySalesPlanList(pageQuerySalePlanRequest);
            if (Objects.nonNull(pageResultResult) && Objects.nonNull(pageResultResult.getResult()) &&
                    org.apache.commons.collections4.CollectionUtils.isNotEmpty(pageResultResult.getResult().getContent())) {
                PageResult<List<SalesPlanSDO>> result = pageResultResult.getResult();
                List<SalesPlanSDO> content = result.getContent();
                SalesPlanSDO salesPlanSDO = content.get(0);
                planId = salesPlanSDO.getId() == null ? null : String.valueOf(salesPlanSDO.getId());
            } else {
                throw new FunctionException("OTS-04-001-00-15-034");
            }

            /**
             * 获取计划明细回复数量
             */
            PageQuerySalesPlanLineList2Request pageQuerySalePlanRequestLine = new PageQuerySalesPlanLineList2Request();
            pageQuerySalePlanRequestLine.setPlanId(planId);
            pageQuerySalePlanRequestLine.setCustomerAddressId(addressSDOId);//"11"
            pageQuerySalePlanRequestLine.setCustomerCode(forecastOrderLineIndex.getMainCustomerCode());//"3730000712");
            pageQuerySalePlanRequestLine.setScItemId(forecastOrderLineIndex.getSubScItemId());//"306188816041963901");
            pageQuerySalePlanRequestLine.setStart(0);
            pageQuerySalePlanRequestLine.setLimit(10);
            Integer totalPlanQty = 0;
            log.info("查询月度计划明细回复量入参：", pageQuerySalePlanRequestLine);
            PageQuerySalesPlanLineList2Response pageResultResult1 = salesPlanService.pageQuerySalesPlanLineList2(pageQuerySalePlanRequestLine);

            if (Objects.nonNull(pageResultResult1) && Objects.nonNull(pageResultResult1.getResult()) &&
                    org.apache.commons.collections4.CollectionUtils.isNotEmpty(pageResultResult1.getResult())) {
                List<SalesPlanLineSDO2> salesPlanLineSDOS = pageResultResult1.getResult();
                SalesPlanLineSDO2 salesPlanLineSDO = salesPlanLineSDOS.get(0);
                totalPlanQty += salesPlanLineSDO.getMonthFirstReturnCount();
                totalPlanQty += salesPlanLineSDO.getMonthMiddleReturnCount();
                totalPlanQty += salesPlanLineSDO.getMonthLastReturnCount();
            } else {
                throw new FunctionException("OTS-04-001-00-15-034");
            }

            CountSaleOrderForReportRequest countSaleOrderForReportRequest = new CountSaleOrderForReportRequest();
            countSaleOrderForReportRequest.setGmtCreateStartTime(DateUtils.firstDayOfMonth());
            countSaleOrderForReportRequest.setGmtCreateEndTime(DateUtils.endDayOfMonth());
            countSaleOrderForReportRequest.setDetailStatusList(Arrays.asList(3, 4));
            countSaleOrderForReportRequest.setScItemId(forecastOrderLineIndex.getSubScItemId());
            log.info("查询统计销售子单发货数入参：", countSaleOrderForReportRequest);
            CountSaleOrderForReportResponse countSaleOrderForReportResponse = otsB2bTradeCenterService.countSaleOrderForReport(countSaleOrderForReportRequest);
            if (Objects.nonNull(countSaleOrderForReportResponse)) {
                planDifferenceQuantity = (totalPlanQty - (int) Float.parseFloat(countSaleOrderForReportResponse.getDeliveryAmount()));
                if (planDifferenceQuantity < 0) {
                    planDifferenceQuantity = 0;
                }
            } else {
                throw new FunctionException("OTS-04-001-00-15-034");
            }
        } catch (Exception e) {
            planDifferenceQuantity = -1;
            log.error("ERROR:计划差量查询失败", e);
        }
        return planDifferenceQuantity;
    }


    private DealForecastOrderResponse convert2DealForecastOrderResponseByIndex(ForecastOrderLineIndex lineIndex, Integer remainCnt, Double inventoryCnt, Long creditCnt) {
        if (lineIndex == null) {
            return null;
        }

        DealForecastOrderResponse dealForecastOrderResponse = new DealForecastOrderResponse();
        //销售组织编码
        dealForecastOrderResponse.setOrganizationCode(lineIndex.getMainOrganizationCode());
        //分销渠道
        dealForecastOrderResponse.setSaleChannelCode(lineIndex.getMainSaleChannelCode());
        //产品组
        dealForecastOrderResponse.setProductGroupCode(lineIndex.getMainProductGroupCode());
        //售达方
        dealForecastOrderResponse.setCustomerCode(lineIndex.getMainCustomerCode());
        //明细id
        dealForecastOrderResponse.setId(String.valueOf(lineIndex.getSubId()));
        //主单id
        dealForecastOrderResponse.setMainOrderId(lineIndex.getSubMainOrderId());
        //预计恢复数量
        dealForecastOrderResponse.setPredictReplyAmount(lineIndex.getSubPredictReplyAmount() == null ? 0 : lineIndex.getSubPredictReplyAmount().intValue());
        //客户名称
        dealForecastOrderResponse.setCustomerName(lineIndex.getMainCustomerName());
        //分析原因
        dealForecastOrderResponse.setAnalysisReason(lineIndex.getSubAnalysisReason());
        //商品名称
        dealForecastOrderResponse.setScItemTitle(lineIndex.getSubScItemTitle());
        //商品名称
        dealForecastOrderResponse.setScItemName(lineIndex.getSubScItemTitle());
        //行号
        dealForecastOrderResponse.setSerialNumber(lineIndex.getSubSerialNumber());
        // 查询可用库存
        Double availableQuantity = Optional.ofNullable(inventoryCnt).orElse(0D);
        dealForecastOrderResponse.setInventory(BigDecimal.valueOf(availableQuantity).setScale(3, RoundingMode.FLOOR).toString());
        //orderNo 订单号
        dealForecastOrderResponse.setOrderNo(String.valueOf(lineIndex.getMainId()));
        //预报数量
        dealForecastOrderResponse.setQuantity(lineIndex.getSubQuantity());
        //actualTotalReplyAmount 累计回复数量
        dealForecastOrderResponse.setActualTotalReplyAmount(lineIndex.getSubActualTotalReplyAmount() == null ? 0 : lineIndex.getSubActualTotalReplyAmount().intValue());
        //promotionId 促销Id
        dealForecastOrderResponse.setPromotionId(lineIndex.getSubActivityCode());
        //promotionDesc 促销描述
        dealForecastOrderResponse.setPromotionDesc(lineIndex.getSubActivityName());
        //unitPrice 单价
        dealForecastOrderResponse.setUnitPrice(lineIndex.getSubUnitPrice());
        //orderTotalFee 总金额
        dealForecastOrderResponse.setOrderTotalFee(lineIndex.getSubTotalFee());
        //salesOrderId 销售单号
        dealForecastOrderResponse.setSalesOrderId(lineIndex.getMainOuterOrderId());
        //消息说明
        dealForecastOrderResponse.setMessageIndicate("销售订单生成成功");
        //备注
        dealForecastOrderResponse.setDetailRemark(lineIndex.getSubDetailRemark());
        //信贷余额
        /**
         * 调用SAP信贷查询接口实时获取，不可编辑
         */
        if (creditCnt != null) {
            dealForecastOrderResponse.setCreditBalance(creditCnt);
        }

        //扣减预报可用库存
        /**
         * 1、调用可用库存查询API获取可用库存
         * 2、计算当前日期预报订单的累计未回复说量
         * 3、该值=1-2
         * 4、不可编辑
         */
        //获取当天已经使用的货品数量
        //通过接口获取每日库存减去已经使用的库存
        if (null != remainCnt) {
            Double deductionInventory = availableQuantity - remainCnt;
            dealForecastOrderResponse.setDeductionInventory(BigDecimal.valueOf(deductionInventory).setScale(3, RoundingMode.FLOOR).toString());
        } else {
            dealForecastOrderResponse.setDeductionInventory(BigDecimal.valueOf(availableQuantity).setScale(3, RoundingMode.FLOOR).toString());
        }

        /**
         * 设置业务单id
         */
        dealForecastOrderResponse.setOrderBizId(lineIndex.getMainOrderBizId());
        /**
         * 货品生产日期
         * 由于es是使用时间戳返回结果  空的话会是0 所以特判
         */
        if (StringUtils.isNotBlank(lineIndex.getSubGoodsProductationTime()) && !("0").equals(lineIndex.getSubGoodsProductationTime())) {
            try {
                Date date = new Date(Long.parseLong(lineIndex.getSubGoodsProductationTime()));
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String format = sdf.format(date);
                dealForecastOrderResponse.setGoodsProductationTime(format);
            } catch (Exception e) {
                log.error("ForecastOrderLineQueryRepositoryImpl|convert2DealForecastOrderResponseByIndex", e);
            }
        }
        /**
         * 拒绝原因
         */
        dealForecastOrderResponse.setRefuseReason(lineIndex.getSubRefuseReason());
        return dealForecastOrderResponse;
    }


    private Long queryCustomerCredit(QueryCreditRequest request) {
        try {
            Result<CreditReponse> result = creditQueryService.queryCreditBalance(request);
            CreditReponse response = result.getResult();
            if (result.isSuccess() || response != null) {
                return MoneyUtil.formatRoundLong(response.getBalance());
            }
        } catch (Exception e) {
            log.error("ERROR:获取信贷余额失败 req:" + JSON.toJSONString(request), e);
        }
        return null;
    }

}
